package com.ruoyi.system.service.impl;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.SysContractRefundMapper;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;

/**
 * 合同退费列Service业务层处理
 *
 * @author ruoyi
 * @date 2025-06-29
 */
@Service
public class SysContractRefundServiceImpl implements ISysContractRefundService
{
    @Autowired
    private SysContractRefundMapper sysContractRefundMapper;

    /** 退费明细service接口层 */
    @Autowired
    private ISysContractRefundLabelService sysContractRefundLabelService;

    /** 合同service接口层 */
    @Autowired
    private ISysContractService sysContractService;

    /** 合同明细service接口层 */
    @Autowired
    private ISysContractLabelService sysContractLabelService;

    /** 合同退费日志service接口层 */
    @Autowired
    private ISysContractRefundLogService sysContractRefundLogService;

    /** 合同退费挽单service接口层 */
    @Autowired
    private ISysContractRefundReportService sysContractRefundReportService;

    /** 角色service接口层 */
    @Autowired
    private ISysRoleService sysRoleService;

    /**
     * 查询合同退费列
     *
     * @param id 合同退费列主键
     * @return 合同退费列
     */
    @Override
    public SysContractRefund selectSysContractRefundById(Long id)
    {
        SysContractRefund sysContractRefund = sysContractRefundMapper.selectSysContractRefundById(id);
        if (null != sysContractRefund){
            //合同退费列明细
            List<SysContractRefundLabel> sysContractRefundLabel = sysContractRefundLabelService.selectSysContractRefundLabelListByRefundId(sysContractRefund.getId());
            if (!CollectionUtils.isEmpty(sysContractRefundLabel)){
                sysContractRefund.setContractRefundLabelList(sysContractRefundLabel);
            }
            //合同退费日志
            List<SysContractRefundLog> sysContractRefundLogList = sysContractRefundLogService.selectSysContractRefundLogListByRefundId(id);
            if (!CollectionUtils.isEmpty(sysContractRefundLogList)){
                sysContractRefund.setContractRefundLogList(sysContractRefundLogList);
            }
            //挽单报告
            SysContractRefundReport sysContractRefundReport = sysContractRefundReportService.selectSysContractRefundReportByContractRefundId(id);
            if (null != sysContractRefundReport){
                sysContractRefund.setContractRefundReport(sysContractRefundReport);
            }
        }
        return sysContractRefund;
    }

    /**
     * 查询合同退费列列表
     *
     * @param sysContractRefund 合同退费列
     * @return 合同退费列
     */
    @Override
    public List<SysContractRefund> selectSysContractRefundList(SysContractRefund sysContractRefund)
    {
        return sysContractRefundMapper.selectSysContractRefundList(sysContractRefund);
    }

    /**
     * 新增合同退费列
     *
     * @param sysContractRefund 合同退费列
     * @return 结果
     */
    @Override
    @Transactional
    public int insertSysContractRefund(SysContractRefund sysContractRefund)
    {
        int status = 0;
        try {
            //新增判断方法
            emptyInsetSysContractRefund(sysContractRefund);

            //查询合同判断是否为校长已确认
            SysContract sysContract = sysContractService.selectSysContractById(sysContractRefund.getContractId());
            if (null == sysContract){
                throw new RuntimeException("未查询到合同信息，请联系管理员");
            }
            if (sysContract.getContractConfirmStatus() != 3){
                throw new RuntimeException("当前合同未审核完，请确认");
            }

            //构建实体
            sysContractRefund = buildSysContractRefund(sysContractRefund);

            //新增方法
            status = sysContractRefundMapper.insertSysContractRefund(sysContractRefund);

            //表体新增方法
            for (int i = 0;i < sysContractRefund.getContractRefundLabelList().size();i++){
                SysContractRefundLabel sysContractRefundLabel = sysContractRefund.getContractRefundLabelList().get(i);
                sysContractRefundLabel.setContractRefundId(sysContractRefund.getId());
                sysContractRefundLabelService.insertSysContractRefundLabel(sysContractRefundLabel);
            }

            //退费合同操作日志
            SysContractRefundLog sysContractRefundLog = new SysContractRefundLog();
            //退费合同主键
            sysContractRefundLog.setContractRefundId(sysContractRefund.getId());
            //新增操作方法
            sysContractRefundLog.setOperate("创建退费信息");
            sysContractRefundLog = sysContractRefundLogService.buildSysContractRefundLog(sysContractRefundLog);

            //退费合同操作日志创建方法
            sysContractRefundLogService.insertSysContractRefundLog(sysContractRefundLog);
        }
        catch (Exception e){
            //事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new RuntimeException(e.getMessage());
        }
        return status;
    }

    /**
     * 构建实体
     * @param sysContractRefund
     * @return
     */
    @Override
    public SysContractRefund buildSysContractRefund(SysContractRefund sysContractRefund) {
        //编码
        sysContractRefund.setContractRefundCode(getSerialNumber());
        //创建人
        //sysContractRefund.setCreateBy(SecurityUtils.getUsername());
        sysContractRefund.setCreateBy("admin");
        //创建时间
        sysContractRefund.setCreateTime(DateUtils.getNowDate());
        //状态
        sysContractRefund.setStatus(0L);
        //退费总金额
        sysContractRefund.setTotalMoney(0L);
        sysContractRefund.getContractRefundLabelList().forEach(it -> {
            //构建明细实体
            sysContractRefundLabelService.buildSysContractRefundLabel(it);
            //退费总金额
            sysContractRefund.setTotalMoney(sysContractRefund.getTotalMoney() + it.getRefundMoney());
        });
        //是否内部退费
        sysContractRefund.setIsInternal(0L);
        return sysContractRefund;
    }

    /**
     *
     * @return
     */
    @Override
    public String getSerialNumber() {
        String serialNumber = "";

        //今天的日期
        String today = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
        //下一级流水号
        int nextSequence;
        int maxSequenceFromDB = getMaxSequenceFromDB(today);

        maxSequenceFromDB += 1;

        //对流水号前拼接流水号
        serialNumber = String.valueOf(maxSequenceFromDB);
        if (serialNumber.length() < 5){
            nextSequence = 5 - serialNumber.length();
            for (int i = 0;i < nextSequence;i++){
                serialNumber = "0" + serialNumber;
            }
        }
        serialNumber = today + serialNumber;
        return serialNumber;
    }

    @Override
    public int getMaxSequenceFromDB(String date) {
        //默认值(当天无记录)
        int maxSeq = 0;
        //查询当天最大流水号
        String sequence = selectContractRefundByDate(date);
        if (null != sequence){
            maxSeq = Integer.parseInt(sequence);
        }
        return maxSeq;
    }

    /**
     * 根据当前日期查询客户
     * @param date
     * @return
     */
    @Override
    public String selectContractRefundByDate(String date) {
        return sysContractRefundMapper.selectContractRefundByDate(date);
    }

    /**
     * 新增创建合同判断方法
     * @param sysContractRefund
     */
    @Override
    public void emptyInsetSysContractRefund(SysContractRefund sysContractRefund) {
        //合同主键
        if (null == sysContractRefund.getContractId()){
            throw new RuntimeException("合同主键未传输，请联系管理员");
        }
        //合同退费明细
        if (CollectionUtils.isEmpty(sysContractRefund.getContractRefundLabelList())){
            throw new RuntimeException("未传输合同退费明细");
        }
        //明细判空方法
        sysContractRefund.getContractRefundLabelList().forEach(it -> {
            sysContractRefundLabelService.emptyInsertSysContractRefundLabel(it);
        });
    }

    /**
     * 修改合同退费列
     *
     * @param sysContractRefund 合同退费列
     * @return 结果
     */
    @Override
    public int updateSysContractRefund(SysContractRefund sysContractRefund)
    {
        return sysContractRefundMapper.updateSysContractRefund(sysContractRefund);
    }

    /**
     * 批量删除合同退费列
     *
     * @param ids 需要删除的合同退费列主键
     * @return 结果
     */
    @Override
    public int deleteSysContractRefundByIds(Long[] ids)
    {
        return sysContractRefundMapper.deleteSysContractRefundByIds(ids);
    }

    /**
     * 删除合同退费列信息
     *
     * @param id 合同退费列主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteSysContractRefundById(Long id)
    {
        int status = 0;
        try {
            //查询退费合同
            SysContractRefund sysContractRefund = this.selectSysContractRefundById(id);
            if (null == sysContractRefund){
                throw new RuntimeException("未查询到退费合同，请联系管理员");
            }
            //判断状态是否可以删除
            if (sysContractRefund.getStatus() != 0){
                throw new RuntimeException("当前合同状态不为新增，不可进行删除");
            }
            //查询退费合同明细
            List<SysContractRefundLabel> sysContractRefundLabelList = sysContractRefundLabelService.selectSysContractRefundLabelListByRefundId(id);
            sysContractRefundLabelList.forEach(it -> {
                //查询合同明细
                SysContractLabel sysContractLabel = sysContractLabelService.selectSysContractLabelById(it.getContractLabelId());
                if (null == sysContractLabel){
                    throw new RuntimeException("未查询到合同明细，请联系管理员");
                }
                //修改合同剩余课时
                sysContractLabel.setRemainingClassTime(sysContractLabel.getRemainingClassTime() + it.getRefundClassTime());
                //修改合同明细
                sysContractLabelService.updateSysContractLabel(sysContractLabel);
                //查询合同
                SysContract sysContract = sysContractService.selectSysContractById(sysContractLabel.getContractId());
                if (null == sysContract){
                    throw new RuntimeException("未查询到合同信息，请联系管理员");
                }
                //修改合同剩余课时
                sysContract.setRemainingClassTime(sysContract.getRemainingClassTime() + it.getRefundClassTime());
                //修改合同
                sysContractService.updateSysContract(sysContract);
            });

            //删除日志
            sysContractRefundLogService.deleteSysContractRefundLogByRefundId(id);

            //删除挽单报告
            sysContractRefundReportService.deleteSysContractRefundReportByRefundId(id);

            //删除退费合同明细
            sysContractRefundLabelService.deleteSysContractRefundLabelByContractRefundId(id);

            //删除退费合同
            this.deleteSysContractRefundById(id);
        }
        catch (Exception e){
            //事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new RuntimeException(e.getMessage());
        }

        return sysContractRefundMapper.deleteSysContractRefundById(id);
    }

    /**
     * 退费合同审核方法
     * @param id
     * @return
     */
    @Override
    @Transactional
    public int approve(Long id) {
        int status = 0;
        try {
            //查询退费合同
            SysContractRefund sysContractRefund = this.selectSysContractRefundById(id);
            if (null == sysContractRefund){
                throw new RuntimeException("未查询到退费合同信息，请联系管理员");
            }
            //待校长审核
            if (sysContractRefund.getStatus() == 1){
                status = cashierApprove(sysContractRefund);
            }
            //待BSC审核
            else if (sysContractRefund.getStatus() == 2){
                status = bscApprove(sysContractRefund);
            }
            //待财务审核
            else if (sysContractRefund.getStatus() == 3){
                status = financeApprove(sysContractRefund);
            }
        }
        catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new RuntimeException(e.getMessage());
        }
        return status;
    }

    /**
     * 校长审核方法
     * @param sysContractRefund
     * @return
     */
    @Override
    @Transactional
    public int cashierApprove(SysContractRefund sysContractRefund) {
        int status = 0;
        try {
            //判断是否为校长
            List<SysRole> sysRoles = sysRoleService.selectRolesByUserId(SecurityUtils.getUserId());
            if (CollectionUtils.isEmpty(sysRoles)) {
                throw new RuntimeException("该用户未有角色不可进行操作");
            }
            boolean flag = false;
            for (int i = 0; i < sysRoles.size(); i++) {
                SysRole sysRole = sysRoles.get(i);
                if (sysRole.getRoleKey().equals("principal")){
                    flag = true;
                }
            }
            if (!flag){
                throw new RuntimeException("当前用户不为校长，不可进行此操作");
            }

            //修改状态为待总部BSC确认
            sysContractRefund.setStatus(2L);

            //添加校长审核人
            sysContractRefund.setCashierId(SecurityUtils.getUserId());

            //添加校长审核时间
            sysContractRefund.setCashierApproveTime(DateUtils.getNowDate());

            //修改退费合同
            this.updateSysContractRefund(sysContractRefund);

            //新增退费合同日志
            SysContractRefundLog sysContractRefundLog = new SysContractRefundLog();
            //创建人
            sysContractRefundLog.setCreateBy(SecurityUtils.getUsername());
            //创建时间
            sysContractRefundLog.setCreateTime(DateUtils.getNowDate());
            //操作
            sysContractRefundLog.setOperate("校长审核");
            //退费合同主键
            sysContractRefundLog.setContractRefundId(sysContractRefund.getId());

            //新增退费合同日志
            status = sysContractRefundLogService.insertSysContractRefundLog(sysContractRefundLog);
        }
        catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new RuntimeException(e.getMessage());
        }
        return status;
    }

    /**
     * 驳回方法
     * @param id
     * @param note
     * @return
     */
    @Override
    @Transactional
    public int unApprove(Long id, String note) {
        int status = 0;
        try {
            //查询合同
            SysContractRefund sysContractRefund = this.selectSysContractRefundById(id);
            if (null == sysContractRefund){
                throw new RuntimeException("未查询到合同信息,请联系管理员");
            }
            //校长驳回
            if (sysContractRefund.getStatus() == 1){
                status = cashierUnApprove(sysContractRefund,note);
            }
            //BSC驳回
            else if (sysContractRefund.getStatus() == 2){
                status = bscUnApprove(sysContractRefund,note);
            }
            //财务驳回
            else if (sysContractRefund.getStatus() == 3){
                status = financeUnApprove(sysContractRefund,note);
            }
            else if (sysContractRefund.getStatus() == 0){
                throw new RuntimeException("当前状态为提交态，不可驳回");
            }
        }
        catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new RuntimeException(e.getMessage());
        }
        return status;
    }

    /**
     * 校长驳回方法
     * @param sysContractRefund
     * @param note
     * @return
     */
    @Override
    @Transactional
    public int cashierUnApprove(SysContractRefund sysContractRefund, String note) {
        int status = 0;
        try {
            //判断是否为校长
            List<SysRole> sysRoles = sysRoleService.selectRolesByUserId(SecurityUtils.getUserId());
            if (CollectionUtils.isEmpty(sysRoles)) {
                throw new RuntimeException("该用户未有角色不可进行操作");
            }
            boolean flag = false;
            for (int i = 0; i < sysRoles.size(); i++) {
                SysRole sysRole = sysRoles.get(i);
                if (sysRole.getRoleKey().equals("principal")){
                    flag = true;
                }
            }
            if (!flag){
                throw new RuntimeException("当前用户不为校长，不可进行此操作");
            }

            //修改状态为新建合同
            sysContractRefund.setStatus(0L);

            //修改退费合同
            this.updateSysContractRefund(sysContractRefund);

            //新增退费合同日志
            SysContractRefundLog sysContractRefundLog = new SysContractRefundLog();
            //创建人
            sysContractRefundLog.setCreateBy(SecurityUtils.getUsername());
            //创建时间
            sysContractRefundLog.setCreateTime(DateUtils.getNowDate());
            //操作
            sysContractRefundLog.setOperate("校长驳回:" + note);
            //退费合同主键
            sysContractRefundLog.setContractRefundId(sysContractRefund.getId());

            //新增退费合同日志
            status = sysContractRefundLogService.insertSysContractRefundLog(sysContractRefundLog);
        }
        catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new RuntimeException(e.getMessage());
        }
        return status;
    }

    /**
     * BSC驳回方法
     * @param sysContractRefund
     * @param note
     * @return
     */
    @Override
    public int bscUnApprove(SysContractRefund sysContractRefund, String note) {
        //判断是否为BSC
        List<SysRole> sysRoles = sysRoleService.selectRolesByUserId(SecurityUtils.getUserId());
        if (CollectionUtils.isEmpty(sysRoles)) {
            throw new RuntimeException("该用户未有角色不可进行操作");
        }
        boolean flag = false;
        for (int i = 0; i < sysRoles.size(); i++) {
            SysRole sysRole = sysRoles.get(i);
            if (sysRole.getRoleKey().equals("bsc")){
                flag = true;
            }
        }
        if (!flag){
            throw new RuntimeException("当前用户不为BSC，不可进行此操作");
        }

        //修改状态为待校长审核
        sysContractRefund.setStatus(1L);

        //删除校长审核人
        sysContractRefund.setCashierId(null);

        //删除校长审核时间
        sysContractRefund.setCashierApproveTime(null);

        //修改退费合同
        this.updateSysContractRefund(sysContractRefund);

        //新增退费合同日志
        SysContractRefundLog sysContractRefundLog = new SysContractRefundLog();
        //创建人
        sysContractRefundLog.setCreateBy(SecurityUtils.getUsername());
        //创建时间
        sysContractRefundLog.setCreateTime(DateUtils.getNowDate());
        //操作
        sysContractRefundLog.setOperate("BSC驳回:" + note);
        //退费合同主键
        sysContractRefundLog.setContractRefundId(sysContractRefund.getId());

        //新增退费合同日志
        return sysContractRefundLogService.insertSysContractRefundLog(sysContractRefundLog);
    }

    /**
     * 财务驳回方法
     * @param sysContractRefund
     * @param note
     * @return
     */
    @Override
    public int financeUnApprove(SysContractRefund sysContractRefund, String note) {
        //判断是否为财务
        List<SysRole> sysRoles = sysRoleService.selectRolesByUserId(SecurityUtils.getUserId());
        if (CollectionUtils.isEmpty(sysRoles)) {
            throw new RuntimeException("该用户未有角色不可进行操作");
        }
        boolean flag = false;
        for (int i = 0; i < sysRoles.size(); i++) {
            SysRole sysRole = sysRoles.get(i);
            if (sysRole.getRoleKey().equals("finance")){
                flag = true;
            }
        }
        if (!flag){
            throw new RuntimeException("当前用户不为财务，不可进行此操作");
        }

        //修改状态为待BSC审核
        sysContractRefund.setStatus(2L);

        //删除BSC审核人
        sysContractRefund.setBscId(null);

        //删除BSC审核时间
        sysContractRefund.setBscApproveTime(null);

        //修改退费合同
        this.updateSysContractRefund(sysContractRefund);

        //新增退费合同日志
        SysContractRefundLog sysContractRefundLog = new SysContractRefundLog();
        //创建人
        sysContractRefundLog.setCreateBy(SecurityUtils.getUsername());
        //创建时间
        sysContractRefundLog.setCreateTime(DateUtils.getNowDate());
        //操作
        sysContractRefundLog.setOperate("财务驳回:" + note);
        //退费合同主键
        sysContractRefundLog.setContractRefundId(sysContractRefund.getId());

        //新增退费合同日志
        return sysContractRefundLogService.insertSysContractRefundLog(sysContractRefundLog);
    }

    /**
     * BSC审核方法
     * @param sysContractRefund
     * @return
     */
    @Override
    public int bscApprove(SysContractRefund sysContractRefund) {
        //判断是否为BSC
        List<SysRole> sysRoles = sysRoleService.selectRolesByUserId(SecurityUtils.getUserId());
        if (CollectionUtils.isEmpty(sysRoles)) {
            throw new RuntimeException("该用户未有角色不可进行操作");
        }
        boolean flag = false;
        for (int i = 0; i < sysRoles.size(); i++) {
            SysRole sysRole = sysRoles.get(i);
            if (sysRole.getRoleKey().equals("bsc")){
                flag = true;
            }
        }
        if (!flag){
            throw new RuntimeException("当前用户不为BSC，不可进行此操作");
        }

        //修改状态为待财务确认
        sysContractRefund.setStatus(3L);

        //添加BSC审核人
        sysContractRefund.setBscId(SecurityUtils.getUserId());

        //添加BSC审核时间
        sysContractRefund.setBscApproveTime(DateUtils.getNowDate());

        //修改退费合同
        this.updateSysContractRefund(sysContractRefund);

        //新增退费合同日志
        SysContractRefundLog sysContractRefundLog = new SysContractRefundLog();
        //创建人
        sysContractRefundLog.setCreateBy(SecurityUtils.getUsername());
        //创建时间
        sysContractRefundLog.setCreateTime(DateUtils.getNowDate());
        //操作
        sysContractRefundLog.setOperate("BSC审核");
        //退费合同主键
        sysContractRefundLog.setContractRefundId(sysContractRefund.getId());

        //新增退费合同日志
        return sysContractRefundLogService.insertSysContractRefundLog(sysContractRefundLog);
    }

    /**
     * 财务审核方法
     * @param sysContractRefund
     * @return
     */
    @Override
    public int financeApprove(SysContractRefund sysContractRefund) {
        //判断是否为财务
        List<SysRole> sysRoles = sysRoleService.selectRolesByUserId(SecurityUtils.getUserId());
        if (CollectionUtils.isEmpty(sysRoles)) {
            throw new RuntimeException("该用户未有角色不可进行操作");
        }
        boolean flag = false;
        for (int i = 0; i < sysRoles.size(); i++) {
            SysRole sysRole = sysRoles.get(i);
            if (sysRole.getRoleKey().equals("finance")){
                flag = true;
            }
        }
        if (!flag){
            throw new RuntimeException("当前用户不为财务，不可进行此操作");
        }

        //修改状态为已确认
        sysContractRefund.setStatus(4L);

        //添加财务审核人
        sysContractRefund.setFinanceId(SecurityUtils.getUserId());

        //添加BSC审核时间
        sysContractRefund.setFinanceApproveTime(DateUtils.getNowDate());

        //修改退费合同
        this.updateSysContractRefund(sysContractRefund);

        //新增退费合同日志
        SysContractRefundLog sysContractRefundLog = new SysContractRefundLog();
        //创建人
        sysContractRefundLog.setCreateBy(SecurityUtils.getUsername());
        //创建时间
        sysContractRefundLog.setCreateTime(DateUtils.getNowDate());
        //操作
        sysContractRefundLog.setOperate("财务审核");
        //退费合同主键
        sysContractRefundLog.setContractRefundId(sysContractRefund.getId());

        //新增退费合同日志
        return sysContractRefundLogService.insertSysContractRefundLog(sysContractRefundLog);
    }
}